/*--------------------------------------------------------------------------------
 * Adaptive Intelligence - Windows Forms Controls Class Library
 * Version 2.00
 * 
 * Line Control Class
 *      Represents a general purpose graphical line control.
 *------------------------------------------------------------------------------*/

/*--------------------------------------------------------------------------------
 * System Imports
 *------------------------------------------------------------------------------*/
using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;
using System.ComponentModel;

namespace Adaptive.Foundation.Windows.Forms
{
    /// <summary>
    /// Represents a general purpose graphical line control.
    /// </summary>
    [Browsable(true), ToolboxItem(true), DesignerCategory("UserControl"),
    System.ComponentModel.Designer(typeof(System.Windows.Forms.Design.ParentControlDesigner))]
    public partial class LineControl : AdaptiveControlBase
    {
        /*--------------------------------------------------------------------------------
         * Public Event Definitions
         *------------------------------------------------------------------------------*/
        #region Public Event Definitions
        #endregion

        /*--------------------------------------------------------------------------------
         * Private Constants Declarations
         *------------------------------------------------------------------------------*/
        #region Private Constants Declarations
        #endregion

        /*--------------------------------------------------------------------------------
         * Private Member Declarations
         *------------------------------------------------------------------------------*/
        #region Private Member Declarations
		/// <summary>
		/// Style of the line to be drawn.
		/// </summary>
		private LineStyle _style = LineStyle.InsetLine;
		/// <summary>
		/// Alignment of the control.
		/// </summary>
		private LineAlignment _alignment = LineAlignment.Horizontal;
		/// <summary>
		/// Starting color for gradient lines.
		/// </summary>
		private Color _startColor;
		/// <summary>
		/// Ending color for gradient lines.
		/// </summary>
		private Color _endColor;
		/// <summary>
		/// Color for colored lines.
		/// </summary>
		private Color _lineColor;
		private int _origWidth;
		private int _origHeight;
		/// <summary>
		/// Gradient direction indicator for gradient lines.
		/// </summary>
		private LinearGradientMode _gradientMode = LinearGradientMode.Horizontal;
        #endregion

        /*--------------------------------------------------------------------------------
         * Constructor / Dispose / Destructor Methods
         *------------------------------------------------------------------------------*/
        #region Constructor / Dispose / Destructor Methods
        /// <summary>
        /// Initializes a new instance of the class.
        /// </summary>
        /// <remarks>
        /// This is the default constructor.
        /// </remarks>
        public LineControl()
            : base()
        {
            SetStyle(ControlStyles.SupportsTransparentBackColor, true);
            SetStyle(ControlStyles.AllPaintingInWmPaint, true);
            SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
            SetStyle(ControlStyles.UserPaint, true);
            
            TabStop = false;
            DoubleBuffered = true;
        }
        /// <summary>
        /// Deallocates internally allocated objects.
        /// </summary>
        /// <param name="disposing">
        /// A value indicating whether the object is being disposed.
        /// </param>
        protected override void Dispose(bool disposing)
        {
            if (disposing)
            {
                if (components != null)
                    components.Dispose();
            }
            components = null;
            base.Dispose(disposing);
        }
        #endregion

        /*------------------------------------------------------------------------
		 * Hidden Properties
		 *----------------------------------------------------------------------*/
        #region Hidden Properties
        /// <summary>
        /// Hides the <see cref="Control.Text"/> property.
        /// </summary>
        /// <value>
        /// Always an empty string.
        /// </value>
        [Browsable(false)]
        internal new string Text
        {
            get { return string.Empty; }
            set { base.Text = string.Empty; }
        }
        /// <summary>
        /// Hides the <see cref="Control.TabStop"/> property.
        /// </summary>
        /// <value>
        /// Always <b>false</b>.
        /// </value>
        [Browsable(false)]
        internal new bool TabStop
        {
            get { return false; }
            set { base.TabStop = false; }
        }
        /// <summary>
        /// Hides the <see cref="Control.TabIndex"/> property.
        /// </summary>
        /// <value>
        /// Always zero (0).
        /// </value>
        [Browsable(false)]
        internal new int TabIndex
        {
            get { return 0; }
            set { base.TabIndex = 0; }
        }
        #endregion

        /*--------------------------------------------------------------------------------
         * Public Properties
         *------------------------------------------------------------------------------*/
        #region Public Properties
        /// <summary>
        /// Gets or sets the type of line that is to be drawn.
        /// </summary>
        /// <value>
        /// A <see cref="LineStyle"/> enumeration value which dictates how the 
        /// line is drawn.
        /// </value>
        [Browsable(true), Category("Appearance"), DefaultValue(LineStyle.SingleLine),
        Description("Gets or sets the type of line that is to be drawn.")]
        public LineStyle Style
        {
            get { return _style; }
            set
            {
                _style = value;
                base.Height = _origHeight;
                base.Width = _origWidth;
                GetCorrectHeight(Height);
                GetCorrectWidth(Width);
                Invalidate();
            }
        }
        /// <summary>
        /// Gets or sets a value indicating whether the line is horizontal or vertical.
        /// </summary>
        /// <value>
        /// A <see cref="LineAlignment"/> value indicating whether the line is to be 
        /// drawn as a horizontal line, or as a vertical line.  This affects the values
        /// of the <see cref="Width"/> and <see cref="Height"/> properties.
        /// </value>
        [Browsable(true), Category("Appearance"), DefaultValue(LineAlignment.Horizontal),
        Description("Gets or sets a value indicating whether the line is horizontal or vertical.")]
        public LineAlignment DirectionAlignment
        {
            get { return _alignment; }
            set
            {
                _alignment = value;
                Invalidate();
            }
        }
        /// <summary>
        /// Gets or sets the <see cref="Color"/> of the line for non-gradient styles.
        /// </summary>
        /// <value>
        /// The <see cref="Color"/> of the line, if it is drawn in a non-gradient style.
        /// </value>
        [Browsable(true), Category("Appearance"),
        Description("Gets or sets the Color of the line for non-gradient styles.")]
        public Color LineColor
        {
            get { return _lineColor; }
            set
            {
                _lineColor = value;
                Invalidate();
            }
        }
        /// <summary>
        /// Gets or sets the <see cref="Color"/> of the line for non-gradient styles.
        /// </summary>
        /// <value>
        /// The <see cref="Color"/> of the line, if it is drawn in a non-gradient style.
        /// </value>
        [Browsable(true), Category("Appearance"),
        Description("Gets or sets the Color of the line for non-gradient styles.")]
        public override Color ForeColor
        {
            get { return _lineColor; }
            set
            {
                _lineColor = value;
                Invalidate();
            }
        }
        /// <summary>
        /// Gets or sets the initial <see cref="Color"/> used to paint a gradient line.
        /// </summary>
        /// <value>
        /// The starting <see cref="Color"/> for the gradient line.
        /// </value>
        [Browsable(true), Category("Appearance"),
        Description("Gets or sets the initial color used to paint a gradient line.")]
        public Color GradientStartColor
        {
            get { return _startColor; }
            set
            {
                _startColor = value;
                Invalidate();
            }
        }
        /// <summary>
        /// Gets or sets the ending <see cref="Color"/> used to paint a gradient line.
        /// </summary>
        /// <value>
        /// The ending <see cref="Color"/> for the gradient line.
        /// </value>
        [Browsable(true), Category("Appearance"),
        Description("Gets or sets the ending color used to paint a gradient line.")]
        public Color GradientEndColor
        {
            get { return _endColor; }
            set
            {
                _endColor = value;
                Invalidate();
            }
        }
        /// <summary>
        /// Gets or sets the height value of the control.
        /// </summary>
        /// <value>
        /// The height, in pixels, of the line control.  This value is read-only if 
        /// the control is in horizontal mode.
        /// </value>
        [Browsable(true), Category("Appearance"),
        Description("Gets or sets the height value of the control.")]
        public new int Height
        {
            get { return base.Height; }
            set
            {
                _origHeight = value;
                base.Height = GetCorrectHeight(value);
                Invalidate();
            }
        }
        /// <summary>
        /// Gets or sets the width value of the control.
        /// </summary>
        /// <value>
        /// The width, in pixels, of the line control.  This value is read-only if 
        /// the control is in vertical mode.
        /// </value>
        [Browsable(true), Category("Appearance"),
        Description("Gets or sets the width value of the control.")]
        public new int Width
        {
            get { return base.Width; }
            set
            {
                _origWidth = value;
                base.Width = GetCorrectWidth(value);
                Invalidate();
            }
        }
        /// <summary>
        /// Gets or sets the size (width, height) of the control.
        /// </summary>
        /// <value>
        /// A Size structure indicating the width and height of the control.
        /// </value>
        [Browsable(true), Category("Appearance"),
        Description("Gets or sets the size (width, height) of the control.")]
        public new System.Drawing.Size Size
        {
            get { return base.Size; }
            set
            {
                Height = value.Height;
                Width = value.Width;
            }
        }
        /// <summary>
        /// Gets or sets the manner and direction in which the line gradient is painted.
        /// </summary>
        /// <value>
        /// A LinearGradientMode value indicating if the gradient is horizontal, vertical,
        /// or diagonal.
        /// </value>
        [Browsable(true), Category("Appearance"),
        Description("Gets or sets the manner and direction in which the line gradient is painted.")]
        public LinearGradientMode GradientMode
        {
            get { return _gradientMode; }
            set
            {
                _gradientMode = value;
                Invalidate();
            }
        }
        #endregion

        /*--------------------------------------------------------------------------------
         * Protected Methods / Event Methods
         *------------------------------------------------------------------------------*/
        #region Protected Methods / Event Methods
        /// <summary>
        /// Paints the control and raises the 
        /// <see cref="System.Windows.Forms.Control.Paint"/> event.
        /// </summary>
        protected override void OnPaint(System.Windows.Forms.PaintEventArgs e)
        {
            if (Visible)
            {
                switch (_style)
                {
                    case LineStyle.SingleLine:
                        DrawSingleLine(e.Graphics);
                        break;

                    case LineStyle.ColorLine:
                        DrawRectangle(e.Graphics, 0, 0, Width, Height, _lineColor);
                        break;

                    case LineStyle.GradientLine:
                        DrawGradientRectangle(e.Graphics, new Rectangle(0, 0, Width, Height),
                            _startColor, _endColor, _gradientMode);
                        break;

                    case LineStyle.InsetColorLine:
                        DrawInsetColorLine(e.Graphics);
                        break;

                    case LineStyle.InsetGradientLine:
                        DrawInsetGradientLine(e.Graphics);
                        break;

                    case LineStyle.InsetLine:
                        DrawInsetLine(e.Graphics);
                        break;

                    case LineStyle.NoLine:
                        break;

                    case LineStyle.RaisedLine:
                        DrawRaisedLine(e.Graphics);
                        break;
                }
                base.OnPaint(e);
            }
        }
        /// <summary>
        /// Re-adjusts the sizing of the control, re-paints, and raises the
        /// <see cref="System.Windows.Forms.Control.Resize"/> event.
        /// </summary>
        protected override void OnResize(System.EventArgs e)
        {
            GetCorrectHeight(base.Height);
            GetCorrectWidth(base.Width);

            if (Visible)
                Invalidate();

            base.OnResize(e);
        }
        /// <summary>
        /// Creates and assigns the event handlers for the items contained within the control.
        /// </summary>
        protected override void AssignEventHandlers()
        {
        }
        /// <summary>
        /// Removes the event handlers for the items contained within the control.
        /// </summary>
        protected override void RemoveEventHandlers()
        {
        }
        /// <summary>
        /// Initializes the content of the control before the event handlers are assigned.
        /// </summary>
        protected override void InitializeContent()
        {
        }
        /// <summary>
        /// This method is invoked in the main UI thread to perform any neccessary
        /// updates to the UI.
        /// </summary>
        /// <remarks>
        /// Calling the related <see cref="AdaptiveControlBase.UpdateControl()"/> is used to prevent illegal 
        /// cross-threaded UI update calls.
        /// </remarks>
        protected override void UpdateCurrentControlContents()
        {
        }
        /// <summary>
        /// This method is invoked in the main UI thread to perform any neccessary
        /// updates to the UI.
        /// </summary>
        /// <remarks>
        /// Calling the related <see cref="AdaptiveControlBase.UpdateControl(object[])"/> is used to prevent illegal 
        /// cross-threaded UI update calls.
        /// </remarks>
        /// <param name="data">
        /// The data supplied to the control to update the internal controls with.
        /// </param>
        protected override void UpdateCurrentControlContents(object[] data)
        {
        }
        #endregion

        /*--------------------------------------------------------------------------------
         * Public Methods / Functions
         *------------------------------------------------------------------------------*/
        #region Public Methods / Functions
        #endregion

        /*--------------------------------------------------------------------------------
         * Private Event Handlers
         *------------------------------------------------------------------------------*/
        #region Private Event Handlers
        #endregion

        /*--------------------------------------------------------------------------------
         * Private Methods / Functions
         *------------------------------------------------------------------------------*/
        #region Private Methods / Functions
        /// <summary>
        /// Returns the control's correct height for the type of line being displayed.
        /// </summary>
        /// <param name="newHeight">The proposed new height for the control.</param>
        /// <returns>
        /// The modified height value, in pixels.
        /// </returns>
        private int GetCorrectHeight(int newHeight)
        {
            int returnValue = 0;			//Return value.

            switch (_alignment)
            {
                case LineAlignment.Horizontal:

                    switch (_style)
                    {
                        case LineStyle.ColorLine:
                        case LineStyle.GradientLine:
                            returnValue = newHeight;
                            break;

                        case LineStyle.RaisedLine:
                        case LineStyle.InsetColorLine:
                        case LineStyle.InsetGradientLine:
                            returnValue = 3;
                            break;

                        case LineStyle.SingleLine:
                        case LineStyle.InsetLine:
                            returnValue = 2;
                            break;

                        case LineStyle.NoLine:
                            returnValue = 0;
                            break;
                    }
                    break;
                case LineAlignment.Vertical:
                    returnValue = newHeight;
                    break;
            }

            base.Height = returnValue;
            return returnValue;
        }
        /// <summary>
        /// Returns the control's correct width for the type of line being displayed.
        /// </summary>
        /// <param name="newWidth">The proposed new width for the control.</param>
        /// <returns>
        /// The modified width value, in pixels.
        /// </returns>
        private int GetCorrectWidth(int newWidth)
        {
            int returnValue = 0;			//Return value.

            switch (_alignment)
            {
                case LineAlignment.Vertical:
                    switch (_style)
                    {
                        case LineStyle.ColorLine:
                        case LineStyle.GradientLine:
                            returnValue = newWidth;
                            break;

                        case LineStyle.InsetColorLine:
                        case LineStyle.InsetGradientLine:
                            returnValue = 3;
                            break;
                        case LineStyle.RaisedLine:
                        case LineStyle.InsetLine:
                            returnValue = 2;
                            break;
                        case LineStyle.NoLine:
                            returnValue = 0;
                            break;

                        case LineStyle.SingleLine:
                            returnValue = 1;
                            break;
                    }
                    break;
                case LineAlignment.Horizontal:
                    returnValue = newWidth;
                    break;
            }

            base.Width = returnValue;
            return returnValue;
        }
        /// <summary>
        /// Draws the control as an inset, colored line.
        /// </summary>
        /// <param name="g">The <see cref="Graphics"/> object used to draw the control.</param>
        private void DrawInsetColorLine(Graphics g)
        {
            DrawThreeDBox(g, 0, 0, Width - 1, Height - 1, true);
            if (_alignment == LineAlignment.Horizontal)
                DrawLine(g, 1, 1, Width - 1, 1, _lineColor);
            else
                DrawLine(g, 1, 1, 1, Height - 2, _lineColor);
        }
        /// <summary>
        /// Draws the control as an inset, gradient-color line.
        /// </summary>
        /// <param name="g">The <see cref="Graphics"/> object used to draw the control.</param>
        private void DrawInsetGradientLine(Graphics g)
        {
            DrawThreeDBox(g, 0, 0, Width - 1, Height - 1, true);
            DrawGradientRectangle(g, new Rectangle(1, 1, Width - 2, Height - 2),
                _startColor, _endColor, _gradientMode);

        }
        /// <summary>
        /// Draws the control as an inset line.
        /// </summary>
        /// <param name="g">The <see cref="Graphics"/> object used to draw the control.</param>
        private void DrawInsetLine(Graphics g)
        {
            if (_alignment == LineAlignment.Horizontal)
            {
                DrawLine(g, 0, 0, Width - 1, 1, SystemColors.ControlDark);
                DrawLine(g, 0, 1, Width - 1, 1, SystemColors.ControlLightLight);
            }
            else
            {
                DrawLine(g, 0, 0, 1, Height - 1, SystemColors.ControlDark);
                DrawLine(g, 1, 0, 1, Height - 1, SystemColors.ControlLightLight);
            }
        }
        /// <summary>
        /// Draws the control as a raised line.
        /// </summary>
        /// <param name="g">The <see cref="Graphics"/> object used to draw the control.</param>
        private void DrawRaisedLine(Graphics g)
        {
            if (_alignment == LineAlignment.Horizontal)
            {
                DrawLine(g, 0, 0, Width - 1, 1, SystemColors.ControlLightLight);
                DrawLine(g, 0, 1, Width - 1, 1, SystemColors.ControlDark);
            }
            else
            {
                DrawLine(g, 0, 0, 1, Height - 1, SystemColors.ControlLightLight);
                DrawLine(g, 1, 0, 1, Height - 1, SystemColors.ControlDark);
            }
        }
        /// <summary>
        /// Draws the control as a single-pixel colored line.
        /// </summary>
        /// <param name="g">The <see cref="Graphics"/> object used to draw the control.</param>
        private void DrawSingleLine(Graphics g)
        {
            if (_alignment == LineAlignment.Horizontal)
                DrawLine(g, 0, 0, Width - 1, 1, SystemColors.ControlText);
            else
                DrawLine(g, 0, 0, 1, Height, SystemColors.ControlText);
        }
        /// <summary>
        /// Draws the specified line.
        /// </summary>
        /// <param name="g">The <see cref="Graphics"/> object used to draw the control.</param>
        /// <param name="x">The starting left or x co-ordinate.</param>
        /// <param name="y">The starting top or y co-ordinate.</param>
        /// <param name="width">The width of the line to be drawn.</param>
        /// <param name="height">The height of the line to be drawn.</param>
        /// <param name="lineColor">The color of the line to be drawn.</param>
        private void DrawLine(Graphics g, int x, int y, int width, int height,
            Color lineColor)
        {
            Pen linePen = null;

            linePen = new Pen(lineColor);
            g.DrawLine(linePen, x, y, x + (width - 1), y + (height - 1));
            linePen.Dispose();
            linePen = null;
        }
        /// <summary>
        /// Draws a three-dimensional raised or inset box.
        /// </summary>
        /// <param name="g">The <see cref="Graphics"/> object used to draw the control.</param>
        /// <param name="x">The starting left or x co-ordinate.</param>
        /// <param name="y">The starting top or y co-ordinate.</param>
        /// <param name="width">The width of the box to be drawn.</param>
        /// <param name="height">The height of the box to be drawn.</param>
        /// <param name="inset">A value indicating whether to draw the box as inset or raised.</param>
        private void DrawThreeDBox(Graphics g, int x, int y, int width, int height,
            bool inset)
        {
            Pen topLeftPen = null;
            Pen bottomRightPen = null;

            //Create pens.
            if (inset)
            {
                topLeftPen = SystemPens.ControlDark;
                bottomRightPen = SystemPens.ControlLight;
            }
            else
            {
                bottomRightPen = SystemPens.ControlDark;
                topLeftPen = SystemPens.ControlLight;
            }

            //Draw lines.
            g.DrawLine(topLeftPen, x, y, x + width, y);
            g.DrawLine(topLeftPen, x, y, x, y + height);
            g.DrawLine(bottomRightPen, x + 1, y + height, x + width, y + height);
            g.DrawLine(bottomRightPen, x + width, y + height, x + width, y + 1);

            topLeftPen = null;
            bottomRightPen = null;
        }
        /// <summary>
        /// Draws the specified gradient rectangle.
        /// </summary>
        /// <param name="g">The <see cref="Graphics"/> object used to draw the control.</param>
        /// <param name="rect">A rectangle describing the co-ordinate bounds.</param>
        /// <param name="startColor">The starting color of the gradient.</param>
        /// <param name="endColor">The ending color of the gradient.</param>
        /// <param name="mode">The gradient drawing mode.</param>
        private void DrawGradientRectangle(Graphics g, Rectangle rect,
            Color startColor, Color endColor, LinearGradientMode mode)
        {
            LinearGradientBrush brush = null;

            brush = new LinearGradientBrush(rect, startColor, endColor, mode);
            g.FillRectangle(brush, rect);
            brush.Dispose();
            brush = null;
        }
        /// <summary>
        /// Draws a the specified rectangle.
        /// </summary>
        /// <param name="g">The <see cref="Graphics"/> object used to draw the control.</param>
        /// <param name="x">The starting left or x co-ordinate.</param>
        /// <param name="y">The starting top or y co-ordinate.</param>
        /// <param name="width">The width of the rectangle to be drawn.</param>
        /// <param name="height">The height of the rectangle to be drawn.</param>
        /// <param name="lineColor">The color of the rectangle to be drawn.</param>
        private void DrawRectangle(Graphics g, int x, int y, int width,
            int height, Color lineColor)
        {
            if (height > 1)
            {
                SolidBrush brush = new SolidBrush(lineColor);
                g.FillRectangle(brush, x, y, width, height);
                brush.Dispose();
                brush = null;
            }
            else
            {
                Pen pen = new Pen(lineColor);
                g.DrawLine(pen, x, y, x + (width - 1), y);
                pen.Dispose();
                pen = null;
            }
        }
        #endregion

    }
}
